package com.zzyl.nursing.service.impl;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.huaweicloud.sdk.iotda.v5.IoTDAClient;
import com.huaweicloud.sdk.iotda.v5.model.*;
import com.zzyl.common.constant.CacheConstants;
import com.zzyl.common.exception.base.BaseException;
import com.zzyl.common.utils.DateUtils;
import com.zzyl.nursing.dto.DeviceDetailVo;
import com.zzyl.nursing.dto.DeviceDto;
import com.zzyl.nursing.util.DateTimeZoneConverter;
import com.zzyl.nursing.vo.DeviceDataVo;
import com.zzyl.nursing.vo.ProductVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import com.zzyl.nursing.mapper.DeviceMapper;
import com.zzyl.nursing.domain.Device;
import com.zzyl.nursing.service.IDeviceService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import java.util.Arrays;

/**
 * 设备管理Service业务层处理
 *
 * @author itzq
 * @date 2025-06-01
 */
@Service
public class DeviceServiceImpl extends ServiceImpl<DeviceMapper, Device> implements IDeviceService {
    @Autowired
    private DeviceMapper deviceMapper;

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    @Autowired
    private IoTDAClient client;     // 华为物联网平台客户端数据采集类

    /**
     * 查询设备管理列表
     *
     * @param device 设备管理
     * @return 设备管理
     */
    @Override
    public List<Device> selectDeviceList(Device device) {
        return deviceMapper.selectDeviceList(device);
    }

    @Override
    public void syncProductList() {
        //请求参数, ListProductsRequest用于封装从java端向三方接口传递产品列表的查询参数。
        ListProductsRequest listProductsRequest = new ListProductsRequest();
        //设置条数
        listProductsRequest.setLimit(50);

        // 结合参数发起请求
        ListProductsResponse response = client.listProducts(listProductsRequest);
        if (response.getHttpStatusCode() != 200) {
            throw new BaseException("物联网接口 - 查询产品，同步失败");
        }
        // 获得产品列表
        List<ProductSummary> products = response.getProducts();
        // IOT_ALL_PRODUCT_LIST是自定义的常量, 作为redis缓存的key
        // 常量值为iot:all_product_list, :代表会创建一个文件夹, 冒号前面的就是文件夹名
        redisTemplate.boundValueOps(CacheConstants.IOT_ALL_PRODUCT_LIST).set(JSONUtil.toJsonStr(products));
    }

    @Override
    public List<ProductVo> allProduct() {
        String string = redisTemplate.boundValueOps(CacheConstants.IOT_ALL_PRODUCT_LIST).get();
        if (string != null) {
            List<ProductVo> productVos = JSONUtil.toList(string, ProductVo.class);
            return productVos;
        }
        return List.of();
    }

    @Override
    public void registerDevice(DeviceDto deviceDto) {
        //  查询设备名称是否重复
        LambdaQueryWrapper<Device> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Device::getIotId, deviceDto.getIotId());
        if (count(queryWrapper) > 0) {
            throw new BaseException("设备名称重复");
        }
        //  查询设备标识是否重复
        queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Device::getNodeId, deviceDto.getNodeId());
        if (count(queryWrapper) > 0) {
            throw new BaseException("设备标识重复");
        }
        //  查询同一个位置是否绑定了相同的产品
        queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Device::getBindingLocation, deviceDto.getBindingLocation());
        queryWrapper.eq(Device::getProductKey, deviceDto.getProductKey());
        if (count(queryWrapper) > 0) {
            throw new BaseException("同一个位置只能绑定一个产品");
        }
        //  调用IOT接口注册设备（注意设备deviceSecret需要自己生成）
        AddDeviceRequest request = new AddDeviceRequest();
        AddDevice body = new AddDevice();
//        body.setDeviceId();
        body.setNodeId(deviceDto.getNodeId());
        body.setDeviceName(deviceDto.getDeviceName());
        body.setProductId(deviceDto.getProductKey());
        // AuthInfo是接入凭证
        AuthInfo authInfo = new AuthInfo();
        String secret = RandomUtil.randomString(32);
        // 随机生成32位字符串作为设备密钥, 存到接入凭证内
        authInfo.setSecret(secret);
        body.setAuthInfo(authInfo);
        body.setDescription(deviceDto.getDeviceDescription());

        request.setBody(body);
        // 调用增加 设备的接口时, 返回的是 一个AddDeviceResponse对象
        AddDeviceResponse response = client.addDevice(request);
        if (response.getHttpStatusCode()!=201) {
            throw new BaseException("IOT设备添加失败");
        }
        //  本地存储设备
        Device device = BeanUtil.toBean(deviceDto, Device.class);
        //  设备id由 IOT自动生成并返回
        device.setIotId(response.getDeviceId());
        //  设备密钥是自己生成的, 作为了创建设备的参数, 这边数据库也要保存
        device.setSecret(secret);
        save(device);
    }

    @Override
    public DeviceDetailVo queryDeviceDetail(String iotId) {
        // IOT查询
        ShowDeviceRequest request = new ShowDeviceRequest();
        request.setDeviceId(iotId);
        ShowDeviceResponse response = client.showDevice(request);
        if (response.getHttpStatusCode()!=200) {
            throw new BaseException("IOT设备查询失败");
        }
        // 本地查询
        Device device = this.getOne(new LambdaQueryWrapper<Device>().eq(Device::getIotId,iotId));
        if (device==null) {
            throw new BaseException("设备不存在");
        }

        DeviceDetailVo deviceDetailVo = BeanUtil.toBean(device, DeviceDetailVo.class);

        //设备状态
        deviceDetailVo.setDeviceStatus(response.getStatus());

        String activeTimeStr = response.getActiveTime();// 2025-06-01T08:24:24.349Z
        // 把字符串转成LocalDateTime
        LocalDateTime parse = null;
        try {
            parse = LocalDateTimeUtil.parse(activeTimeStr, DatePattern.UTC_MS_PATTERN);
        } catch (Exception e) {
            throw new BaseException( "设备未激活");
        }
        // DateTimeZoneConverter是今天资料中提供的一个工具类
        LocalDateTime activeTime = DateTimeZoneConverter.utcToShanghai(parse);
        deviceDetailVo.setActiveTime(activeTime);
        return deviceDetailVo;
    }

    @Override
    public List<DeviceDataVo>queryServiceProperties(String iotId) {

        List<DeviceDataVo> list = new ArrayList<>();


        // IOT查询数据
        ShowDeviceShadowRequest request = new ShowDeviceShadowRequest();
        request.setDeviceId(iotId);
        ShowDeviceShadowResponse response = client.showDeviceShadow(request);
        if (response.getHttpStatusCode()!=200) {
            throw new BaseException("IOT设备查询失败");
        }

        List<DeviceShadowData> shadowList = response.getShadow();
        if(CollUtil.isNotEmpty(shadowList)){

            DeviceShadowData deviceShadowData = shadowList.get(0);
            DeviceShadowProperties reported = deviceShadowData.getReported();
            String eventTimeStr = reported.getEventTime();//20250601 T 08 24 34 Z
            LocalDateTime eventTimeUTC = LocalDateTimeUtil.parse(eventTimeStr, "yyyyMMdd'T'HHmmss'Z'");
            LocalDateTime eventTime = DateTimeZoneConverter.utcToShanghai(eventTimeUTC);

            Object properties = reported.getProperties();
            JSONObject jsonObject = JSONUtil.parseObj(properties);
            jsonObject.forEach((key,value)->{
                DeviceDataVo deviceDataVo = new DeviceDataVo();
                deviceDataVo.setFunctionId(key);
                deviceDataVo.setEventTime(eventTime);
                deviceDataVo.setValue(value);
                list.add(deviceDataVo);
            });
        }
        return list;
    }

}
